import tkinter as tk
from tkinter import filedialog, scrolledtext, messagebox
import os
from PIL import Image
import pandas as pd
import datetime
from openpyxl.styles import PatternFill
import logging  # 新增：导入日志模块
import colorsys  # 新增导入模块

class PNGColorAnalyzer:
    def __init__(self, root):
        self.root = root
        self.root.title("PNG颜色分析工具")
        self.root.geometry("700x500")
        
        # 创建UI元素
        self.create_widgets()
        
        # 存储结果数据
        self.results = []
        
    def create_widgets(self):
        # 输入框标签
        tk.Label(self.root, text="输入关键词（每行一个）:").pack(pady=5)
        
        # 多行文本框
        self.text_input = scrolledtext.ScrolledText(self.root, width=70, height=10)
        self.text_input.pack(pady=5, padx=10)
        
        # 文件夹选择按钮
        self.folder_path = tk.StringVar()
        folder_frame = tk.Frame(self.root)
        tk.Button(folder_frame, text="选择文件夹", command=self.select_folder).pack(side=tk.LEFT, padx=5)
        tk.Label(folder_frame, textvariable=self.folder_path, width=50, anchor=tk.W).pack(side=tk.LEFT)
        folder_frame.pack(pady=5)
        
        # 开始处理按钮
        tk.Button(self.root, text="开始处理", command=self.process_files, bg="#4CAF50", fg="white", padx=20).pack(pady=15)
        
        # 状态标签
        self.status_label = tk.Label(self.root, text="就绪", fg="blue")
        self.status_label.pack(pady=10)
        
        # 说明标签
        tk.Label(self.root, text="说明：程序将查找文件名包含关键词的PNG文件，并获取(10,10)坐标的RGB值", fg="gray").pack(side=tk.BOTTOM, pady=10)
        
        # 新增底部标签
        tk.Label(self.root, text="Techlink-数字化中心-李辉能", fg="gray").pack(side=tk.BOTTOM, pady=5)
    
    def select_folder(self):
        folder = filedialog.askdirectory()
        if folder:
            self.folder_path.set(folder)
    
    def process_files(self):
        # 获取输入的关键词
        keywords = [line.strip() for line in self.text_input.get("1.0", tk.END).splitlines() if line.strip()]
        if not keywords:
            messagebox.showwarning("警告", "请输入至少一个关键词")
            return
        
        # 获取选择的文件夹
        folder = self.folder_path.get()
        if not folder:
            messagebox.showwarning("警告", "请选择文件夹")
            return
        
        # 重置结果
        self.results = []
        
        # 遍历文件夹及子文件夹中的PNG文件
        self.status_label.config(text="处理中...")
        self.root.update()
        
        file_count = 0
        matched_count = 0
        
        # 按输入关键词顺序处理，确保结果顺序一致
        for keyword in keywords:
            found = False  # 新增：标记是否找到匹配文件
            for root_dir, dirs, files in os.walk(folder):
                for file in files:
                    if file.lower().endswith(".png"):
                        file_count += 1
                        file_path = os.path.join(root_dir, file)
                        # 检查文件名是否包含当前关键词
                        if keyword.lower() in file.lower():
                            matched_count += 1
                            self.process_png_file(file_path, keyword)
                            found = True  # 找到匹配文件，更新标志
                            break  # 每个文件只匹配第一个关键词
            # 新增：如果没有找到匹配文件，添加空行
            if not found:
                self.results.append({
                    "关键词": keyword,
                    "文件路径": "",
                    "文件名": "",
                    "RGB值": "",
                    "颜色预览": None,  # 空行的颜色预览设为None
                    "错误信息": "未找到匹配文件"
                })
                
        self.status_label.config(text=f"处理完成 - 共扫描{file_count}个PNG文件，匹配{matched_count}个")
        # 生成Excel
        self.generate_excel()
    
    def process_png_file(self, file_path, keyword):
        rgb_values = None
        hex_color = ''
        hsl_color = ''
        try:
            with Image.open(file_path) as img:
                # 转换为RGB模式，处理RGBA等情况
                img_rgb = img.convert('RGB')
                width, height = img_rgb.size
                
                # 验证像素位置是否在图片范围内
                if width > 10 and height > 10:
                    r, g, b = img_rgb.getpixel((10, 10))
                    color = f'RGB({r}, {g}, {b})'
                    rgb_values = (r, g, b)
                    # 计算十六进制颜色值
                    hex_color = f'#{r:02x}{g:02x}{b:02x}'.lower()
                    # 计算HSL颜色值
                    h, s, l = colorsys.rgb_to_hls(r / 255.0, g / 255.0, b / 255.0)
                    hsl_color = f'HSL({int(h * 360)}, {int(s * 100)}%, {int(l * 100)}%)'
                    error = ''
                    logging.info(f'成功获取 {file_path} 的RGB值: {rgb_values}')  # 记录成功信息
                else:
                    color = ''
                    error = f'图片尺寸过小（{width}x{height} < 11x11）'
                    logging.warning(f'{file_path} 尺寸过小: {width}x{height}')  # 记录警告信息
        except Image.DecompressionBombError:
            color = ''
            error = '图片过大，无法处理'
            logging.error(f'{file_path} 图片过大')  # 记录错误信息
        except Exception as e:
            color = ''
            error = f'处理错误: {str(e)}'
            logging.error(f'处理 {file_path} 时出错: {str(e)}')  # 记录错误信息

        # 添加到结果 - 颜色预览字段设为空字符串
        self.results.append({
            '关键词': keyword,
            '文件路径': file_path,
            '文件名': os.path.basename(file_path),
            'RGB值': color,
            '十六进制值': hex_color,
            'HSL值': hsl_color,
            '颜色预览': '',  # 设为空字符串，不显示文字
            '_rgb_data': rgb_values,  # 内部使用的RGB数据
            '错误信息': error
        })
    
    def process_files(self):
        # 获取输入的关键词
        keywords = [line.strip() for line in self.text_input.get("1.0", tk.END).splitlines() if line.strip()]
        if not keywords:
            messagebox.showwarning("警告", "请输入至少一个关键词")
            return
        
        # 获取选择的文件夹
        folder = self.folder_path.get()
        if not folder:
            messagebox.showwarning("警告", "请选择文件夹")
            return
        
        # 重置结果
        self.results = []
        
        # 遍历文件夹及子文件夹中的PNG文件
        self.status_label.config(text="处理中...")
        self.root.update()
        
        file_count = 0
        matched_count = 0
        
        # 按输入关键词顺序处理，确保结果顺序一致
        for keyword in keywords:
            found = False
            for root_dir, dirs, files in os.walk(folder):
                for file in files:
                    if file.lower().endswith(".png"):
                        file_count += 1
                        file_path = os.path.join(root_dir, file)
                        # 原检查文件名是否包含当前关键词
                        # if keyword.lower() in file.lower():
                        # 修改为精确匹配检查
                        if self.is_keyword_in_filename(file.lower(), keyword.lower()):
                            matched_count += 1
                            self.process_png_file(file_path, keyword)
                            found = True
                            break
            # 如果没有找到匹配文件，添加空行
            if not found:
                self.results.append({
                    "关键词": keyword,
                    "文件路径": "",
                    "文件名": "",
                    "RGB值": "",
                    "颜色预览": "",  # 空行也不显示文字
                    "_rgb_data": None,
                    "错误信息": "未找到匹配文件"
                })
                
        self.status_label.config(text=f"处理完成 - 共扫描{file_count}个PNG文件，匹配{matched_count}个")
        # 生成Excel
        self.generate_excel()
    
    def generate_excel(self):
        if not self.results:
            messagebox.showinfo('信息', '没有找到匹配的文件')
            return

        # 创建DataFrame并删除内部使用的RGB数据列
        df = pd.DataFrame(self.results).drop(columns=['_rgb_data'], errors='ignore')
        
        # 自动生成带时间戳的文件名并保存到项目根目录
        project_root = os.path.dirname(os.path.abspath(__file__))
        timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
        filename = f"png_color_result_{timestamp}.xlsx"
        save_path = os.path.join(project_root, filename)
        
        try:
            # 使用openpyxl引擎保存xlsx文件，并设置颜色预览
            with pd.ExcelWriter(save_path, engine='openpyxl') as writer:
                df.to_excel(writer, index=False, sheet_name='结果')
                workbook = writer.book
                worksheet = writer.sheets['结果']
                
                # 获取颜色预览列的索引
                color_col_idx = None
                for col_idx, col_name in enumerate(df.columns):
                    if col_name == "颜色预览":
                        color_col_idx = col_idx + 1  # Excel列索引从1开始
                        break
                
                # 设置颜色预览列的单元格背景色（仅显示颜色，无文字）
                if color_col_idx is not None:
                    for row_idx, result in enumerate(self.results, start=2):  # 从第二行开始（跳过表头）
                        rgb_tuple = result.get("_rgb_data")
                        if rgb_tuple and isinstance(rgb_tuple, tuple) and len(rgb_tuple) == 3:
                            r, g, b = rgb_tuple
                            hex_color = f"{r:02x}{g:02x}{b:02x}"
                            fill = PatternFill(start_color=hex_color, end_color=hex_color, fill_type="solid")
                            worksheet.cell(row=row_idx, column=color_col_idx).fill = fill
                
                # 调整列宽
                for column_cells in worksheet.columns:
                    length = max(len(str(cell.value)) for cell in column_cells) if column_cells else 10
                    worksheet.column_dimensions[column_cells[0].column_letter].width = min(length + 2, 30)  # 限制最大宽度
        
            messagebox.showinfo("成功", f"Excel文件已保存至:\n{save_path}")
            
            # 自动打开Excel文件
            try:
                os.startfile(save_path)
            except Exception as open_e:
                messagebox.showwarning("警告", f"文件已保存，但无法自动打开:\n{str(open_e)}")
                
        except Exception as e:
            messagebox.showerror("错误", f"保存Excel失败:\n{str(e)}")

    def is_keyword_in_filename(self, filename, keyword):
        # 检查关键词是否独立出现在文件名中
        import re
        pattern = rf'\b{re.escape(keyword)}\b'
        return bool(re.search(pattern, filename))

if __name__ == "__main__":
    root = tk.Tk()
    app = PNGColorAnalyzer(root)
    root.mainloop()